<?php

/**
 * 附件接口
 * Some rights reserved：abc3210.com
 * Contact email:admin@abc3210.com
 */
class AttachmentService {

        private $db, $path, $Config, $Ftpstatus, $Ftp;
        //时间
        public $time;
        //上传用户ID
        public $userid;
        //是否后台上传
        public $isadmin;
        //上传模块
        public $module;
        //上传栏目ID
        public $catid = 0;
        // 上传日期目录
        public $dateFormat = "Y/m";
        //附件临时编号
        public $filepass;
        //上传成功以后，完整附件物理地址
        public $filepath;
        //上传成功以后，完整的网络地址
        public $filehttp;

        function __construct($variable) {
                extract($variable);
                $this->module = $module ? strtolower($module) : "contents";
                $this->userid = 1;
                $this->isadmin = (int) $isadmin;
                $this->catid = (int) $catid;
                $this->time = time();
                //附件数据库模型
                $this->db = D("Attachment");
                //附件上传存放目录
                $this->path = C("UPLOADFILEPATH");
                //网站配置
                $this->Config = F("Config");
                if ((int) $this->Config['ftpstatus']) {
                        import('Ftp');
                        $this->Ftp = new Ftp();
                        $this->ftpsta = $this->Ftp->connect($this->Config['ftphost'], $this->Config['ftpuser'], $this->Config['ftppassword'], $this->Config['ftpport'], $this->Config['ftppasv'], $this->Config['ftpssl'], $this->Config['ftptimeout']);
                        $this->Ftpstatus = true;
                }
        }

        //设置附件路径
        public function path($path) {
                $this->path = $path;
        }

        //设置用户ID
        public function set_userid($uid = false) {
                $this->userid = (int) $uid;
        }

        /**
         * 图片加水印 
         * @param type $source 原图文件名。
         * @param type $water 水印图片文件名
         * @param type $savename 要保存的图片名，如果留空则用source
         * @param type $alpha  水印图片的alpha值，默认为80，范围为0~100
         * @param type $waterPos 水印位置。
         * @param type $quality jpg图片质量
         */
        public function water($source, $water = null, $savename = null, $alpha = null, $waterPos = null, $quality = null) {
                import("Image");
                //设置默认水印
                if ($water == '') {
                        $water = SITE_PATH . $this->Config['watermarkimg'];
                }
                //图像信息
                $sInfo = Image::getImageInfo($source);
                //如果图片小于系统设置，不进行水印添加
                if ($sInfo["width"] < (int) $this->Config['watermarkminwidth'] || $sInfo['height'] < (int) $this->Config['watermarkminheight']) {
                        return false;
                }
                //水印位置
                if (empty($waterPos)) {
                        $waterPos = (int) $this->Config['watermarkpos'];
                }
                //水印透明度
                if (empty($alpha)) {
                        $alpha = (int) $this->Config['watermarkpct'];
                }
                //jpg图片质量
                if (empty($quality)) {
                        $quality = (int) $this->Config['watermarkquality'];
                }
                return Image::water($source, $water, $savename, $alpha, $waterPos, $quality);
        }

        /**
         * 远程保存
         * @param $value 传入下载内容
         * @param $watermark 是否加入水印
         * @param $ext 下载扩展名
         */
        public function download($value, $watermark = '', $ext = 'gif|jpg|jpeg|bmp|png') {
                //检查是否有开启CURL
                if (!function_exists('curl_init')) {
                        return $value;
                }
                if ($watermark == '') {
                        if ($this->Config['watermarkenable']) {
                                $watermark = true;
                        }
                }

                $curl = curl_init();
                //正则匹配是否有符合数据
                if (!preg_match_all("/(href|src)=([\"|']?)([^ \"'>]+\.($ext))\\2/i", $value, $matches)) {
                        return $value;
                }
                $remotefileurls = array();
                //过滤域名 
                $NoDomain = explode("|", CONFIG_FILEEXCLUDE);
                //当前程序所在域名地址
                $NoDomain[] = urlDomain(get_url());
                //附件地址
                $upload_url = urlDomain(CONFIG_SITEFILEURL);
                foreach ($matches[3] as $matche) {
                        //过滤远程地址
                        if (strpos($matche, '://') === false) {
                                continue;
                        }
                        //过滤后台设置的域名，和本站域名
                        if (in_array(urlDomain($matche), $NoDomain)) {
                                continue;
                        }
                        $remotefileurls[] = $matche;
                }
                //保存目录
                $FilePath = $this->FilePath();
                $oldpath = $newpath = array();
                import('UploadFile');
                $upload = new UploadFile();
                foreach ($remotefileurls as $k => $file) {
                        if (strpos($file, '://') === false || strpos($file, $upload_url) !== false) {
                                continue;
                        }
                        //取得文件扩展
                        $file_fileext = fileext($file);
                        //取得文件名
                        $file_name = basename($file);
                        //保存文件名
                        $filename = uniqid() . "." . $file_fileext;
                        // 设置你需要抓取的URL
                        curl_setopt($curl, CURLOPT_URL, $file);
                        // 设置header
                        curl_setopt($curl, CURLOPT_HEADER, 0);
                        // 设置cURL 参数，要求结果保存到字符串中还是输出到屏幕上。
                        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
                        //超时设置
                        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
                        // 运行cURL，请求网页
                        $filedata = curl_exec($curl);
                        //保存图片
                        $status = $this->build_file($filedata, $FilePath . "/" . $filename);
                        if ($status) {
                                //加水印
                                if ($watermark) {
                                        $this->water($FilePath . "/" . $filename, "", $FilePath . "/" . $filename);
                                }
                                $oldpath[] = $file;
                                $newpath[] = str_replace($this->path, CONFIG_SITEFILEURL, $FilePath . "/" . $filename);
                                $info = array(
                                    "name" => $file_name,
                                    "type" => "",
                                    "size" => filesize($FilePath . "/" . $filename),
                                    "key" => "",
                                    "extension" => $file_fileext,
                                    "savepath" => $FilePath,
                                    "savename" => "/" . $filename,
                                    "hash" => md5(str_replace($this->path, "", $FilePath . "/" . $filename)),
                                );
                                $aid = $this->FileData($info);
                                //设置标识
                                $this->upload_json($aid, $this->filehttp, $filename);
                                //FTP
                                if ($this->Ftpstatus) {
                                        // 远程存放地址
                                        $remote = $this->Config['ftpuppat'] . str_replace(SITE_PATH . "/", "", $FilePath . "/" . $filename);
                                        if ($upload->FTPuplode($FilePath . "/" . $filename, $remote)) {
                                                //删除
                                                unlink($FilePath . "/" . $filename);
                                        }
                                }
                        }
                }
                // 关闭URL请求
                curl_close($curl);
                $value = str_replace($oldpath, $newpath, $value);
                return $value;
        }

        /**
         * 保存上传成功后的信息到数据库
         * @param type $info 
         */
        public function FileData($info, $isthumb = '0') {
                /**
                 * $info
                 * array (
                  'name' => '6.jpg',
                  'type' => 'application/octet-stream',
                  'size' => 112102,
                  'key' => 0,
                  'extension' => 'jpg',
                  'savepath' => '/home/wwwroot/lvyou.abc3210.com/d/file/contents/2012/07',
                  'savename' => '/5002ba343fc9d.jpg',
                  'hash' => '77b5118c1722da672b0ddce3c4388e64',
                  )
                 */
                if (!is_array($info)) {
                        return false;
                }
                //保存上传后的物理地址
                $this->filepath = $info['savepath'] . $info['savename'];
                $this->filehttp = CONFIG_SITEFILEURL . str_replace($this->path, "", $info['savepath'] . $info['savename']);

                $db = M("Attachment");
                $aid = $db->add(array(
                    //模块名称
                    "module" => $this->module,
                    //栏目ID
                    "catid" => $this->catid,
                    //附件名称
                    "filename" => $info['name'],
                    //附件路径，不包含附件目录 例如 contents/2012/07/5002ba343fc9d.jpg
                    "filepath" => str_replace($this->path, "", $info['savepath'] . $info['savename']),
                    //附件大小
                    "filesize" => $info['size'],
                    //附件扩展名
                    "fileext" => $info['extension'],
                    //是否为图片附件
                    "isimage" => in_array($info['extension'], array("jpg", "png", "jpeg", "gif")) ? 1 : 0,
                    //是否为缩略图
                    "isthumb" => $isthumb,
                    //上传用户ID
                    "userid" => $this->userid,
                    //是否后台上传
                    'isadmin' => $this->isadmin,
                    //上传时间
                    "uploadtime" => $this->time,
                    //上传IP
                    "uploadip" => get_client_ip(),
                    //附件状态
                    "status" => 0,
                    //附件hash
                    "authcode" => $info['hash'],
                ));
                return $aid;
        }

        /**
         * 取得文件保存路径
         * @param type 
         */
        public function FilePath() {
                $this->FilePath = "./d/file/";
                //检测目录是否存在，不存在创建
                if (!is_dir($this->FilePath)) {
                        if (!mkdir($this->FilePath, 0777, true)) {
                                return false;
                        }
                }
                return $this->FilePath;
        }

        /**
         * 删除附件。
         * @param type $aid 附件id
         */
        public function del($aid) {
                if ($this->Ftpstatus) {
                        if ($this->ftpsta == false) {
                                $this->error = 'FTP链接失败' . $this->Config['ftphost'];
                                return false;
                        }
                }
                $data = $this->db->where(array("aid" => $aid))->find();
                if ($data) {
                        $filepath = $data['filepath'];
                        $status = $this->db->where(array("aid" => $aid))->delete();
                        if ($status) {
                                //FTP删除
                                if ($this->Ftpstatus) {
                                        // 远程存放地址
                                        $remote = $this->Config['ftpuppat'] . str_replace(SITE_PATH . "/", "", $this->path . $filepath);
                                        $status = $this->FTPdel($remote);
                                        return $status;
                                } else {
                                        return unlink($this->path . $filepath);
                                }
                        }
                } else {
                        return false;
                }
        }

        /**
         * FTP文件删除
         * @param type $path FTP上的文件路径
         */
        public function FTPdel($path) {
                if ($this->Ftpstatus) {
                        return $this->Ftp->f_delete($path);
                }
                return false;
        }

        /**
         * FTP文件夹删除
         * @param type $path FTP上的文件夹路径
         * @param boolean $enforce 强制删除
         */
        public function FTPrmdir($path, $enforce = false) {
                if ($this->Ftpstatus) {
                        return $this->Ftp->rmdir($path, $enforce);
                }
                return false;
        }

        /**
         * 生成文件
         * @param type $file 需要写入的文件或者二进制流
         * @param type $filename 需要生成的文件名的绝对路径
         * @return boolean 
         */
        protected function build_file($file, $filename) {
                $write = @fopen($filename, "w");
                if ($write == false) {
                        return false;
                }
                if (fwrite($write, $file) == false) {
                        return false;
                }
                if (fclose($write) == false) {
                        return false;
                }
                return true;
        }

        /**
         * 通过附件关系删除附件 
         * @param type $keyid 关联ID
         * @return boolean 布尔值
         */
        public function api_delete($keyid) {
                if (empty($keyid)) {
                        return false;
                }
                $db = M("AttachmentIndex");
                $data = $db->where(array("keyid" => $keyid))->select();
                if ($data) {
                        foreach ($data as $aid) {
                                //统计使用同一个附件的次数，如果大于一，表示还有其他地方使用，将不删除附件
                                $count = $db->where(array("aid" => $aid['aid']))->count();
                                if ($count > 1) {
                                        //只删除附件关系，不删除真实附件
                                        continue;
                                } else {
                                        if ($this->del($aid['aid'])) {
                                                
                                        } else {
                                                return false;
                                        }
                                }
                        }
                }
                $db->where(array("keyid" => $keyid))->delete();
                return true;
        }

        /**
         * 附件更新接口.
         * @param string $content 可传入空，html，数组形式url，url地址，传入空时，以cookie方式记录。
         * @param string 传入附件关系表中的组装id
         * @isurl intval 为本地地址时设为1,以cookie形式管理时设置为2
         */
        public function api_update($content, $keyid, $isurl = 0) {
                $keyid = trim($keyid);
                $isurl = intval($isurl);
                if ($isurl == 2 || empty($content)) {
                        $this->api_update_cookie($keyid);
                } else {
                        $att_index_db = M("Attachment_index");
                        //http附件地址 http://file.abc3210.com/d/file/
                        $upload_url = CONFIG_SITEFILEURL;
                        if (strpos($upload_url, '://') !== false) {
                                $pos = strpos($upload_url, "/", 8);
                                //附件域名 http://file.abc3210.com/
                                $domain = substr($upload_url, 0, $pos) . '/';
                                //附件目录 d/file/
                                $dir_name = substr($upload_url, $pos + 1);
                        } else {
                                //如果附件地址是类似“/d/file/”这样的
                                $dir_name = $upload_url;
                        }
                        if ($isurl == 0) {//分析$content中的附件地址
                                $pattern = '/(href|src)=\"(.*)\"/isU';
                                preg_match_all($pattern, $content, $matches);
                                if (is_array($matches) && !empty($matches)) {
                                        //移除数组中的重复的值
                                        $att_arr = array_unique($matches[2]);
                                        //开始计算md5
                                        foreach ($att_arr as $_k => $_v) {
                                                $att_arrs[$_k] = md5(str_replace(array($domain, $dir_name), '', $_v));
                                        }
                                }
                        } elseif ($isurl == 1) {//不用分析$content中的地址，$content本身就是一个地址，或者是一个一个数组的情况
                                //如果传入的是数组
                                if (is_array($content)) {
                                        $att_arr = array_unique($content);
                                        foreach ($att_arr as $_k => $_v) {
                                                $att_arrs[$_k] = md5(str_replace(array($domain, $dir_name), '', $_v));
                                        }
                                } else {
                                        $att_arrs[] = md5(str_replace(array($domain, $dir_name), '', $content));
                                }
                        }
                        //删除旧的关联关系，从新绑定附件和信息关系
                        $att_index_db->where(array('keyid' => $keyid))->delete();
                        if (is_array($att_arrs) && !empty($att_arrs)) {
                                foreach ($att_arrs as $r) {
                                        $aid = M("Attachment")->where(array('authcode' => $r))->getField("aid");
                                        if ($aid) {
                                                M("Attachment")->where(array('aid' => $aid))->save(array('status' => 1));
                                                $att_index_db->add(array('keyid' => $keyid, 'aid' => $aid), array(), true);
                                        }
                                }
                        }
                }
                //删除附件cookie
                cookie('att_json', NULL);
                return true;
        }

        /**
         * cookie 方式关联附件
         * @param type $keyid 关联ID
         * @return boolean 失败返回false
         */
        private function api_update_cookie($keyid) {
                $att_index_db = M("Attachment_index");
                $att_json = cookie('att_json');
                if ($att_json) {
                        $att_cookie_arr = explode('||', $att_json);
                        $att_cookie_arr = array_unique($att_cookie_arr);
                } else {
                        return false;
                }
                foreach ($att_cookie_arr as $_att_c) {
                        $att[] = json_decode($_att_c, true);
                }
                foreach ($att as $_v) {
                        M("Attachment")->where(array('aid' => $_v['aid']))->save(array('status' => 1));
                        $att_index_db->add(array('keyid' => $keyid, 'aid' => $_v['aid']));
                }
        }

        /**
         * 设置upload上传的json格式cookie 
         * @param type $aid 附件ID
         * @param type $src 附件地址
         * @param type $filename 附件名称
         * @return boolean 返回布尔值
         */
        public function upload_json($aid, $src, $filename) {
                $arr['aid'] = $aid;
                $arr['src'] = trim($src);
                $arr['filename'] = urlencode($filename);
                $json_str = json_encode($arr);
                $att_arr_exist = cookie('att_json');
                $att_arr_exist_tmp = explode('||', $att_arr_exist);
                if (is_array($att_arr_exist_tmp) && in_array($json_str, $att_arr_exist_tmp)) {
                        return true;
                } else {
                        $json_str = $att_arr_exist ? $att_arr_exist . '||' . $json_str : $json_str;
                        cookie('att_json', $json_str);
                        return true;
                }
        }

}

?>
